package com.qunar.wan.service;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.qunar.wan.common_api.model.*;
import com.qunar.wan.common_api.model.enums.ActivityState;
import com.qunar.wan.common_api.model.enums.EmailType;
import com.qunar.wan.common_api.service.*;
import com.qunar.wan.common_api.service.mapper.ActivityMapper;
import com.qunar.wan.service.*;
import com.qunar.wan.common_api.serializer.RowBounds;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * User: cyoung Date: 11/25/13 Time: 6:47 PM
 */
@Service("activityService")
public class ActivityServiceImpl extends BaseServiceImpl<Activity, ActivityMapper> implements ActivityService {

    @Resource
    private UserService userService;
    @Resource
    private AdminLogService adminLogService;
    @Resource
    private EmailService emailTaskService;
    @Resource
    private UserClassifyService userClassifyService;
    @Resource
    private CacheService cacheService;

    /**
     * 用于排序的数据库字段
     */
    private final String CREATE_TIME = "create_time";
    private final String START_TIME = "start_time";
    private final String PEOPLE_NUM = "people_num";
    /**
     * 审核成功
     */
    private final Query CHECK_SUCCESS = new Query("state", ActivityState.CHECK_SUCCESS);
    /**
     * 活动尚未举办
     */
    private final Query NOT_EXPIRED = new Query("beforeStart", new Date()).and(CHECK_SUCCESS);
    /**
     * 所属分类必须alive
     */
    private final Query SUB_ALIVE = new Query("subAlive", "YES");

    @Override
    public List<Activity> selectHots(RowBounds rowBounds) {
        Query query = new Query();
        query.and(NOT_EXPIRED).and(SUB_ALIVE).addSort(new Sort(PEOPLE_NUM, Sort.Order.DESC));
        return wrapperActivity(selectByQuery(query, rowBounds));
    }

    @Override
    @Transactional
    public void examine(Activity activity, User admin) {
        checkNotNull(activity);
        checkNotNull(admin);
        AdminLog adminLog = new AdminLog();
        adminLog.setAction(String.format("审核%s:%s", activity.getTitle(), activity.getState()));
        adminLog.setUserId(admin.getId());
        adminLog.setActionTime(new Date());
        adminLogService.insertObj(adminLog);

        updateObj(activity);
        // TODO 发邮件改成异步
        User sponor = checkNotNull(userService.selectUserById(activity.getUserId()));
        if (activity.getState() == ActivityState.CHECK_FAILURE) {
            logger.info("发送审核不通过邮件到{}", sponor.getEmail());
            emailTaskService.send(EmailType.ACTIVITY_EXAMINE_FAIL, activity.getId(), sponor.getEmail());
        }
        if (activity.getState() == ActivityState.CHECK_SUCCESS) {
            long start = System.currentTimeMillis();
            emailTaskService.send(EmailType.ACTIVITY_EXAMINE_SUCCESS, activity.getId(), sponor.getEmail());
            long end1 = System.currentTimeMillis();
            logger.info("发送审核通过邮件(ID:{},Title:{})到{},耗时{}ms", activity.getId(), activity.getTitle(), sponor.getEmail(),
                    end1 - start);
            List<String> emails = Lists.transform(userClassifyService.selectUsers(activity.getSubClaId()),
                    new Function<User, String>() {
                        @Override
                        public String apply(User user) {
                            return user.getEmail();
                        }
                    });
            if (emails.contains(sponor.getEmail())) {
                emails.remove(sponor.getEmail());
            }
            emailTaskService.send(EmailType.NOTICE_FOLLOWER_EMAIL, activity.getId(), emails);
            logger.info("发送邮件到关注(ID:{},Title:{})耗时{}ms", activity.getId(), activity.getTitle(),
                    System.currentTimeMillis() - end1);
        }
    }

    @Override
    public Activity selectById(int activityId) {
        checkArgument(activityId > 0, "activityId must greater than 0");
        Query query = new Query("id", activityId);
        List<Activity> activities = selectByQuery(query);
        return activities.isEmpty() ? null : wrapperActivity(activities.get(0));
    }

    @Override
    public List<Activity> selectPublished(int userId, RowBounds rowBounds) {
        checkArgument(userId > 0, "userId must greater than 0");
        Query query = new Query("userId", userId).fill("state", ActivityState.CHECK_SUCCESS).addSort(
                new Sort("id", Sort.Order.DESC));
        return wrapperActivity(selectByQuery(query, rowBounds));
    }

    @Override
    public int selectPublishedCount(int userId) {
        checkArgument(userId > 0, "userId must greater than 0");
        Query query = new Query("userId", userId).addSort(new Sort("id", Sort.Order.DESC)).and(CHECK_SUCCESS);
        List<Activity> activities = selectByQuery(query);
        return activities.size();
    }

    @Override
    public List<Activity> selectNotExamined(RowBounds rowBounds) {
        Query query = new Query("state", ActivityState.CHECKING).addSort(new Sort(CREATE_TIME, Sort.Order.ASC))
                .addSort(new Sort(START_TIME, Sort.Order.ASC));
        return wrapperActivity(selectByQuery(query, rowBounds));
    }

    @Override
    public int selectNotExaminedCount() {
        List<Activity> activities = selectNotExamined(new RowBounds(0, 100));
        return activities.size();
    }

    @Override
    public List<Activity> selectByDays(int claId, int subClaId, String[] days, RowBounds rowBounds) {
        checkArgument(days.length > 0, "日期不能为空");
        Query query = new Query("days", days).and(CHECK_SUCCESS);
        if (subClaId > 0) {
            query.fill("subClaId", subClaId);
            return wrapperActivity(selectByQuery(query, rowBounds));
        }
        if (claId > 0) {
            query.fill("claId", claId);
        }
        return wrapperActivity(selectByQuery(query, rowBounds));
    }

    @Override
    public int selectCountByDays(int claId, int subClaId, String[] days) {
        Query query = new Query("days", days).and(CHECK_SUCCESS);
        if (subClaId > 0) {
            query.fill("subClaId", subClaId);
            return selectCount(query);
        }
        query.fill("claId", claId);
        return selectCount(query);
    }

    @Override
    public List<Activity> selectByStartDay(Date date) {
        checkNotNull(date);
        Query query = new Query("startDay", date).and(CHECK_SUCCESS);
        return wrapperActivity(selectByQuery(query));
    }

    @Override
    public List<Activity> selectByEndDay(Date date) {
        checkNotNull(date);
        Query query = new Query("endDay", date).and(CHECK_SUCCESS);
        return wrapperActivity(selectByQuery(query));
    }

    @Override
    public List<Activity> selectByClassify(int claId, int subClaId, boolean showExpired, RowBounds rowBounds) {
        checkNotNull(claId);
        Query query = new Query().and(CHECK_SUCCESS).addSort(new Sort(PEOPLE_NUM, Sort.Order.DESC))
                .addSort(new Sort(START_TIME, Sort.Order.DESC));
        if (!showExpired) {
            query.and(NOT_EXPIRED);
        }
        if (subClaId > 0) {
            query.fill("subClaId", subClaId);
            return wrapperActivity(selectByQuery(query, rowBounds));
        }
        query.fill("claId", claId);
        return wrapperActivity(selectByQuery(query, rowBounds));
    }

    @Override
    public int selectCountByClassify(int claId, int subClaId, boolean showExpired) {
        Query query = new Query().and(CHECK_SUCCESS);
        if (!showExpired) {
            query.and(NOT_EXPIRED);
        }
        if (subClaId > 0) {
            query.fill("subClaId", subClaId);
            return selectCount(query);
        }
        query.fill("claId", claId);
        return selectCount(query);
    }

    private Activity wrapperActivity(Activity activity) {
        checkNotNull(activity);
        // SubClassify subClassify = subClassifyService.selectSubClassifyById(activity.getSubClaId(), false);
        SubClassify subClassify = cacheService.readSingleSubClassifyCache(activity.getSubClaId());
        // activity.setClassifyName(classifyService.selectClassifyById(subClassify.getSupId()).getClaName());
        activity.setClassifyName(cacheService.readSingleClassifyCache(subClassify.getSupId()).getClaName());
        activity.setSubClassifyName(subClassify.getSubName());
        activity.setClassifyId(subClassify.getSupId());
        User sponor = userService.selectUserById(activity.getUserId());
        /** 发起人被删除时屏蔽该活动 */
        if (null == sponor) {
            return null;
        }
        activity.setSponor(userService.selectUserById(activity.getUserId()).getUserName());
        return activity;
    }

    private List<Activity> wrapperActivity(List<Activity> activities) {
        for (Activity activity : activities) {
            wrapperActivity(activity);
        }
        List<Activity> nullActivity = new ArrayList<Activity>(1);
        nullActivity.add(null);
        /** 去除NULL */
        activities.removeAll(nullActivity);
        return activities;
    }

}
